package com.example.mydownloader.netty

import com.example.mydownloader.netty.inBound.NettyMsgDecryptHandler
import com.example.mydownloader.netty.inBound.NettyMsgHandler
import com.example.mydownloader.netty.outBound.NettyMsgEncryptHandler
import io.netty.bootstrap.Bootstrap
import io.netty.channel.Channel
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelFutureListener
import io.netty.channel.ChannelInitializer
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioSocketChannel

object NettyClient {

    var channel: Channel? = null

    fun connect(
        host: String,
        port: Int,
        nettyListener: NettyListener? = null,
        connCount: Int
    ) {
        val eventExecutors = NioEventLoopGroup()
        try {
            // 创建bootstrap对象，配置参数
            val bootstrap = Bootstrap()
            // 设置线程组
            bootstrap.group(eventExecutors)
                .channel(NioSocketChannel::class.java)
                .handler(object : ChannelInitializer<SocketChannel>() {
                    @Throws(Exception::class)
                    override fun initChannel(ch: SocketChannel) {
                        val pipeline = ch.pipeline()
                        // inBound
                        pipeline?.addLast(NettyMsgDecryptHandler())
                        // outBound
                        pipeline?.addLast(NettyMsgEncryptHandler())
                        // inBound
                        pipeline?.addLast(NettyMsgHandler())
                    }
                })
            // 连接服务端
            val channelFuture: ChannelFuture = bootstrap.connect(host, port).sync()
            // 监听连接状况
            channelFuture.addListener(ChannelFutureListener {
                if (channelFuture.isSuccess) {
                    this.channel = channelFuture.channel()
                    nettyListener?.onConnectSuccess(host, port, connCount)
                } else {
                    nettyListener?.onConnectFail(host, port, connCount, channelFuture.cause())
                }
            })
            // 对通道关闭进行监听
            channelFuture.channel().closeFuture().sync()
        } finally {
            // 关闭线程组
            eventExecutors.shutdownGracefully()
        }
    }
}